package com.newcapec.shiro.shiro;


import com.newcapec.shiro.entity.Resources;
import com.newcapec.shiro.entity.Roles;
import com.newcapec.shiro.entity.UserInfo;
import com.newcapec.shiro.service.ResourcesService;
import com.newcapec.shiro.service.RolesService;
import com.newcapec.shiro.service.UsersService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.xkp.ColorPrint;

import java.util.List;

/**
 * Shiro用于身份认证和权限鉴定的自定义Realm类
 */
@Slf4j
public class CustomRealm extends AuthorizingRealm {

    /**
     * 注入用户，角色，权限业务类
     */
    /**
     * 当springboot+redis+shiro整合时，在自定义realm中redis缓存不生效
     * 原因：shiro的加载顺序比缓存加载顺序要早，所有缓存注解@Cacheable不生效
     * 解决：仅需要将加载顺序调整，shiro加载放置在缓存之后
     * 具体实现：在自定义realm中依赖注入Service时需要采用延迟加载模式即可
     */
    @Autowired
    @Lazy
    private UsersService usersService;
    @Autowired
    @Lazy
    private RolesService rolesService;
    @Autowired
    @Lazy
    private ResourcesService resourcesService;

    /**
     * 权限鉴定
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        log.info("权限鉴定doGetAuthorizationInfo...");

        //获取当前登录用户的主标识就是UserInfo对象
        UserInfo userInfo = (UserInfo) principalCollection.getPrimaryPrincipal();

        //查询当前登录用户的角色集合和权限集合
        List<Roles> rolesList = rolesService.findByUserId(userInfo.getId());
        List<Resources> resourcesList = resourcesService.findByUserId(userInfo.getId());
//

       SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        for (Roles roles : rolesList) {
            simpleAuthorizationInfo.addRole(roles.getRoleCode());
        }
        for (Resources resources : resourcesList) {
            simpleAuthorizationInfo.addStringPermission(resources.getPercode());
        }
        ColorPrint.redPrintln(simpleAuthorizationInfo.getStringPermissions());
//        Set<String> roles=new HashSet<>();
//        roles.add("admin");
//        roles.add("root");
//        roles.add("guest");
//        simpleAuthorizationInfo.setRoles(roles);
//
//
//        simpleAuthorizationInfo.addStringPermission("edit");
        return simpleAuthorizationInfo;
    }

    /**
     * 身份认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        log.info("身份认证doGetAuthenticationInfo...");
        //将AuthenticationToken转换为UsernamePasswordToken
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        //获取用户名
        String username = usernamePasswordToken.getUsername();

        //调用用户服务，查询用户信息，获取登录用户
        UserInfo userInfo = usersService.findByUsername(username);

//        SimpleAuthenticationInfo simpleAuthenticationInfo =
//                new SimpleAuthenticationInfo(userInfo, userInfo.getPassword(), ByteSource.Util.bytes(userInfo.getSalt()), this.getName());

        SimpleAuthenticationInfo simpleAuthenticationInfo =
                new SimpleAuthenticationInfo(userInfo, userInfo.getPassword(), ByteSource.Util.bytes(userInfo.getSalt()) , this.getName());

        return simpleAuthenticationInfo;
    }
}
